
#include "platform.h"

#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <mach/vm_statistics.h>

/*
 * Constants used for mmap.
 * kMmapFd is used to pass vm_alloc flags to tag the region with the user
 * defined tag 251 This helps identify mgen-allocated regions in memory analysis
 * tools like vmmap(1).
 */
static const int kMmapFd = VM_MAKE_TAG(251);
static const int kMmapFdOffset = 0;

void *
mgen_allocate(size_t requested, size_t * allocated, bool is_executable) {
    size_t pagesize = getpagesize();
    size_t pages_cnt = requested / pagesize;
    size_t msize;

    if (0 == (requested % pagesize)) {
	msize = pages_cnt * pagesize;
    } else {
	msize = (pages_cnt + 1) * pagesize;
    }

    assert(msize > 0);

    int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
    void * mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON,
			kMmapFd, kMmapFdOffset);

    if (mbase == MAP_FAILED) {
	return NULL;
    }

    *allocated = msize;
    return mbase;
}


void
mgen_free(void * ptr, size_t size) {
    int result = munmap(ptr, size);
    assert(result == 0);
}

